package se.webbzon.boltzmann.minigame.question;

import java.util.ArrayList;
import java.util.Collection;

import se.webbzon.boltzmann.input.Button;
import se.webbzon.boltzmann.input.Input;
import se.webbzon.boltzmann.input.InputListener;
import se.webbzon.boltzmann.minigame.page.DefaultPage;
import se.webbzon.boltzmann.minigame.page.PageItem;
import se.webbzon.boltzmann.minigame.page.PageLayout;
import se.webbzon.oschi01.worldarea.WorldArea;

public class QuestionPage extends DefaultPage {
	
	// A collection of all the listeners to this question page
	private final Collection<QuestionListener> listeners;
	
	// The input listener of this question page
	private final InputListener listener;
	
	// The number of alternatives and the selected alternative
	// The answer to the question
	private int alts, alt, answer;
	
	/*============================================================
	Constructors
	============================================================*/

	public QuestionPage(PageLayout layout, Input input) {
		super(layout, input);
		listener = new InputListenerImpl();
		listeners = new ArrayList<QuestionListener>();
		alts = 0;
		alt = 0;
		answer = 0;
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Adds a listener to this question page. **/
	public boolean addListener(QuestionListener listener) {
		return listeners.add(listener);
	}
	
	/** Removes a listener from this question page. **/
	public boolean removeListener(QuestionListener listener) {
		return listeners.remove(listener);
	}
	
	/** Clears all listeners from this question page. **/
	public void clearListeners() {
		listeners.clear();
	}
	
	/** Returns the number of alternatives of this question page. **/
	public int alternatives() {
		return alts;
	}
	
	/** Returns the selected alternative. If the alternative is zero or
	 * negative then no alternative is selected. **/
	public int getAlternative() {
		return alt;
	}
	
	/** Changes the alternative index to the next or the previous index. **/
	public void changeAlternative(boolean next) {
		final int alt = next ? this.alt + 1 : this.alt - 1;
		boolean changed = false;
		for (int i = 0; i < items(); i++) {
			PageItem item = getItem(i);
			if (item instanceof AlternativeItem) {
				if (((AlternativeItem) item).getAlternative() == alt) {
					changed = true;
					break;
				}
			}
		}
		
		if (changed) {
			for (int i = 0; i < items(); i++) {
				PageItem item = getItem(i);
				if (item instanceof AlternativeItem) {
					AlternativeItem a = (AlternativeItem) item;
					a.setSelected(a.getAlternative() == alt);
				}
			}
			this.alt = alt;
		}
	}
	
	/** Submits this question page. **/
	public void submit() {
		for (QuestionListener listener : listeners.toArray(new QuestionListener[0]))
			listener.onSubmit(this, alt == answer);
	}
	
	@Override public boolean addItem(PageItem item) {
		if (item instanceof AlternativeItem) {
			if (alts == 0) {
				AlternativeItem a = (AlternativeItem) item;
				alt = a.getAlternative();
				a.setSelected(true);
			}
			alts++;
		} else if (item instanceof AnswerItem) {
			answer = ((AnswerItem) item).getAnswer();
		}
		return super.addItem(item);
	}

	@Override public boolean removeItem(PageItem item) {
		if (item instanceof AlternativeItem) {
			alts--;
		}
		return super.removeItem(item);
	}

	@Override public void clearItems() {
		alts = 0;
		super.clearItems();
	}

	@Override public void onCreate(WorldArea world) {
		getInput().addListener(listener);
		super.onCreate(world);
	}

	@Override public void onDestroy(WorldArea world) {
		getInput().removeListener(listener);
		super.onDestroy(world);
	}

	/*============================================================
	Protected Methods
	============================================================*/

	@Override protected void onMoveUp() {
		if (getAlternative() == 1)
			super.onMoveUp();
		else
			changeAlternative(false);
	}

	@Override protected void onMoveDown() {
		if (atBottom() && getAlternative() < 2)
			changeAlternative(true);
		else
			super.onMoveDown();
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private final class InputListenerImpl implements InputListener {

		@Override public void primaryAxisChanged(Input input, double direction, double value) {};

		@Override public void secondaryAxisChanged(Input input, double direction, double value) {};

		@Override public void buttonPressed(Input input, Button button) {
			final int alt = getAlternative();
			if (button == Button.LEFT && alt > 1) {
				changeAlternative(false);
			} else if (button == Button.RIGHT && alt < alternatives()) {
				changeAlternative(true);
			} else if (button == Button.ACTION) 
				submit();
		}

		@Override public void buttonReleased(Input input, Button button) {};

		@Override public void bindingAccepted(Input input, Button button) {};
		
	}
	

}
